#include "pool.h"
#include "topo.h"
#include <iostream>
#include <sstream>
#include <readline/readline.h>
#include <readline/history.h>

extern Topo* g_topo_ptr;

void cli_loop(Pool& pool) {
    while (true) {
        char* input = readline("chunkmaster> ");
        if (!input) break;
        if (*input) add_history(input);
        std::string line(input);
        free(input);
        std::istringstream iss(line);
        std::string cmd;
        iss >> cmd;
        if (cmd == "help") {
            std::cout << "可用命令：\n"
                      << "  show pool            —— 显示Pool基本信息\n"
                      << "  show pg <id>         —— 显示指定PG的分布\n"
                      << "  show chunk <id>      —— 显示指定chunk的PG及盘分布\n"
                      << "  show topo            —— 显示所有服务器和磁盘信息\n"
                      << "  show disk <s> <d>    —— 显示指定服务器指定磁盘承载的PG\n"
                      << "  show chunk           —— 显示已分配chunk数量和所有chunkid\n"
                      << "  show server <idx>    —— 显示指定server的SN和所有磁盘SN及容量\n"
                      << "  alloc chunk          —— 分配一个新的chunkid\n"
                      << "  exit/quit            —— 退出CLI\n"
                      << "  help                 —— 显示本帮助信息\n";
        } else if (cmd == "show" || cmd == "ls") {
            std::string what;
            iss >> what;
            if (what == "pool") {
                std::cout << "EC策略: " << pool.get_ec_data() << "+" << pool.get_ec_parity() << std::endl;
                std::cout << "PG数量: " << pool.get_pg_count() << std::endl;
            } else if (what == "pg") {
                int pgid;
                iss >> pgid;
                if (pgid >= 0 && pgid < pool.get_pg_count()) {
                    const auto& pg = pool.pgs()[pgid];
                    std::cout << "PG " << pgid << " 分布: ";
                    for (auto& loc : pg.disk_locs) {
                        std::cout << "[S" << loc.first << "-D" << loc.second << "] ";
                    }
                    std::cout << std::endl;
                } else {
                    std::cout << "无效PG编号" << std::endl;
                }
            } else if (what == "topo") {
                if (!g_topo_ptr) {
                    std::cout << "Topo信息未初始化" << std::endl;
                } else {
                    const auto& servers = g_topo_ptr->servers();
                    for (size_t i = 0; i < servers.size(); ++i) {
                        std::cout << "Server " << i << " SN: " << servers[i].sn << std::endl;
                        for (size_t j = 0; j < servers[i].disks.size(); ++j) {
                            std::cout << "  Disk " << j << " SN: " << servers[i].disks[j].sn << ", Size: " << servers[i].disks[j].size_gb << "MB" << std::endl;
                        }
                    }
                }
            } else if (what == "disk") {
                int sidx, didx;
                iss >> sidx >> didx;
                if (!g_topo_ptr) {
                    std::cout << "Topo信息未初始化" << std::endl;
                } else {
                    const auto& servers = g_topo_ptr->servers();
                    if (sidx < 0 || sidx >= (int)servers.size() || didx < 0 || didx >= (int)servers[sidx].disks.size()) {
                        std::cout << "无效的服务器或磁盘编号" << std::endl;
                    } else {
                        std::cout << "Server " << sidx << " Disk " << didx << " SN: " << servers[sidx].disks[didx].sn << std::endl;
                        std::cout << "承载PG: ";
                        for (int pgid = 0; pgid < pool.get_pg_count(); ++pgid) {
                            const auto& pg = pool.pgs()[pgid];
                            for (auto& loc : pg.disk_locs) {
                                if (loc.first == sidx && loc.second == didx) {
                                    std::cout << pgid << " ";
                                    break;
                                }
                            }
                        }
                        std::cout << std::endl;
                    }
                }
            } else if (what == "chunk") {
                std::string next;
                iss >> next;
                if (!next.empty() && std::all_of(next.begin(), next.end(), ::isdigit)) {
                    uint64_t cid = std::stoull(next);
                    const ChunkMeta* meta = pool.get_chunk_meta(cid);
                    if (!meta) {
                        std::cout << "chunkid " << cid << " 不存在" << std::endl;
                    } else {
                        std::cout << "chunkid: " << cid << std::endl;
                        std::cout << "PG: " << meta->pg_id << std::endl;
                        const PG* pg = pool.get_pg(meta->pg_id);
                        if (pg) {
                            std::cout << "Disks: ";
                            for (auto& loc : pg->disk_locs) {
                                std::cout << "[S" << loc.first << "-D" << loc.second << "] ";
                            }
                            std::cout << std::endl;
                        }
                    }
                } else {
                    std::cout << "已分配chunk数量: " << pool.allocated_chunk_count() << std::endl;
                    std::cout << "已分配chunkid: ";
                    for (auto cid : pool.allocated_chunks()) std::cout << cid << " ";
                    std::cout << std::endl;
                }
            } else if (what == "server") {
                int sidx;
                iss >> sidx;
                if (!g_topo_ptr) {
                    std::cout << "Topo信息未初始化" << std::endl;
                } else {
                    const auto& servers = g_topo_ptr->servers();
                    if (sidx < 0 || sidx >= (int)servers.size()) {
                        std::cout << "无效的服务器编号" << std::endl;
                    } else {
                        std::cout << "Server " << sidx << " SN: " << servers[sidx].sn << std::endl;
                        for (size_t j = 0; j < servers[sidx].disks.size(); ++j) {
                            std::cout << "  Disk " << j << " SN: " << servers[sidx].disks[j].sn << ", Size: " << servers[sidx].disks[j].size_gb << "MB" << std::endl;
                        }
                    }
                }
            }
        } else if (cmd == "alloc" && line.find("chunk") != std::string::npos) {
            ChunkMeta meta = pool.alloc_chunkid_balanced();
            std::cout << "分配chunkid: " << meta.chunk_id << ", PG: " << meta.pg_id << ", Disks: ";
            const PG* pg = pool.get_pg(meta.pg_id);
            if (pg) {
                for (auto& loc : pg->disk_locs) {
                    std::cout << "[S" << loc.first << "-D" << loc.second << "] ";
                }
            }
            std::cout << std::endl;
        } else if (cmd == "exit" || cmd == "quit") {
            break;
        } else {
            std::cout << "未知命令" << std::endl;
        }
    }
} 